import json
import re
import traceback
import sys
import os
import io
from pathlib import Path

from nonebot.adapters import Bot, Event
from nonebot_plugin_alconna import Alconna, on_alconna, Args, Option, Arparma, CommandMeta
from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot_plugin_htmlrender import (
    template_to_pic,
)
from PIL import Image



current_dir = os.path.dirname(os.path.abspath(__file__))

# 获取 drawchart_lib.py 所在的目录
drawchart_lib_dir = os.path.join(current_dir)
# 将该目录添加到 sys.path 中
sys.path.append(drawchart_lib_dir)
from drawchart_lib import create_ranking_chart

qrcode_image_path = os.path.join(current_dir, "qsfrontend_nginx_weilaiyun_qrcode_arrow.png")


usage_string = "qs用法： qs -s <计分板名(time|finaltime|level|record_time)> -o <输出模式(raw|pretty|simple|chart|pptr)>" 

# 定义Alconna命令
scoreboard_command = on_alconna(
    Alconna(
        "qwq_scoreboard",  # 主命令名
        Args(),
        Option("--output_mode|-o",      Args["output_mode_str", str], ),
        Option("--scoreboard_name|-s",  Args["scoreboard_name_str",  str]),
        meta=CommandMeta(
            description="查询qwq拨无因果的神秘小服服的计分板数据",
            usage=usage_string,
            example="qs -s finaltime -o pptr",
            author="VincentZyu",
            fuzzy_match=True,
            fuzzy_threshold=0.8,
            raise_exception=True
        ),
        
    ),

    aliases={".qs", "qs"}
)

# 处理命令的函数
@scoreboard_command.handle()
async def handle_scoreboard_command(bot: Bot, event: Event, result: Arparma):

    try:
        
        if "help" in result.options:
            await scoreboard_command.send(usage_string)
            return
        
        # await scoreboard_command.send(f"result.options = {result.options}")
        
        output_mode_str_value = "pretty"
        scoreboard_name_str_value = "finaltime"
        is_reversed = False
        
        if "output_mode" in result.options:
            output_mode_str_value = result.options["output_mode"].args.get('output_mode_str')
            
        if "scoreboard_name" in result.options:
            scoreboard_name_str_value = result.options["scoreboard_name"].args.get('scoreboard_name_str')
        
        if output_mode_str_value not in ["raw", "simple", "pretty", "chart", "pptr"]:
            await scoreboard_command.send(f"模式选项{output_mode_str_value}不存在！输出模式fallback至pretty")
            await scoreboard_command.send(usage_string)
            output_mode_str_value = "pretty"
        
        if scoreboard_name_str_value == "level":
            output_mode_str_value = "simple"
            is_reversed = True
            
        if output_mode_str_value == "chart":
            is_reversed = True
        
        # 输出这些值
        # await scoreboard_command.send(f"output_mode_str_value = {output_mode_str_value}, scoreboard_str_value = {scoreboard_name_str_value}")
        
        scoreboard_data = read_and_parse_scoreboard_file(scoreboard_name_str_value)
        
                # 如果计分板文件不存在，返回错误信息
        if scoreboard_data == "FileNotFoundError":
            await scoreboard_command.send(f"计分板文件 '{scoreboard_name_str_value}_logging.txt' 未找到！计分板选项fallback至finaltime")
            await scoreboard_command.send(usage_string)
            scoreboard_name_str_value = "finaltime"
            scoreboard_data = read_and_parse_scoreboard_file()
            

        sorted_scoreboard_data = filter_and_sort_scoreboard(scoreboard_data, is_reversed)
        
            
        await scoreboard_command.send(f"【qwq_scoreboard】你选择的输出模式 = {output_mode_str_value}，计分板名称 = {scoreboard_name_str_value}")
        
        if output_mode_str_value == "raw":
            await scoreboard_command.send(json.dumps(sorted_scoreboard_data, ensure_ascii=False, indent=4))
        elif output_mode_str_value == "simple":
            simple_output = [
                "---跑酷成绩计分板-S8赛季-跑酷蛋-ParkourEgg-simple---"
            ]
            for entry in sorted_scoreboard_data:
                simple_output.append(f"【{entry['playername']}】 {entry['data']}")
            await scoreboard_command.send("\n".join(simple_output))
        elif output_mode_str_value == "pretty":

            # 发送本地图片
            await scoreboard_command.send(MessageSegment.image(f"file:///{qrcode_image_path}"))

            pretty_output = [
                "点击此链接查看计分板：http://qsfrontend.vincentzyu233.xyz/\n"
                "---跑酷成绩计分板-S8赛季-跑酷蛋-ParkourEgg-pretty---\n",
                # "【本期速通视频】供参考: 【🏆创造奇迹！究极含金量的世界纪录！进来享受完美丝滑的MC跑酷！首个sub640！通关维度跑酷只需要10分37秒？！🏆】 https://www.bilibili.com/video/BV1brHFehECL"
                "【本期速通视频】供参考: 【【前世界纪录】跑酷鸡蛋Parkour Egg 9:30 by perpexior】 https://www.bilibili.com/video/BV1Y841197RW/?share_source=copy_web&vd_source=98321787c4b12bb055fe4e464f59a872\n"
            ]
            for rank, entry in enumerate(sorted_scoreboard_data, start=1):
                minutes = entry['data'] // 60
                seconds = entry['data'] % 60
                pretty_output.append(f"No.{rank} 【{entry['playername']}】 {minutes} m {seconds} s")
            await scoreboard_command.send("\n".join(pretty_output))
            
            
        elif output_mode_str_value == "chart":
            if len(sorted_scoreboard_data)==0:
                await scoreboard_command.send("当前计分板数据为空，matplotlib会报错的qwq，无法生成图表！")
                return
            chart_file_path = f"chart_{scoreboard_name_str_value}.png"
            create_ranking_chart(sorted_scoreboard_data, chart_file_path, is_reversed)

            # 读取图片文件
            with open(chart_file_path, 'rb') as f:
                image_data = f.read()

            # 构建消息，包含文字和图片
            message = MessageSegment.text(f"图表已生成：") + MessageSegment.image(image_data)

            # 发送消息
            await scoreboard_command.send(message)
            
        elif output_mode_str_value == "pptr":
            template_path = str(Path(__file__).parent / "templates")
            template_name = "qs.html"
            
            pic = await template_to_pic(
                template_path=template_path,
                template_name=template_name,
                templates={"sorted_scoreboard_data": sorted_scoreboard_data},
                pages={
                    "viewport": {"width": 600, "height": 300},
                    "base_url": f"file://{template_path}",
                },
                wait=2,
            )
            
            a = Image.open(io.BytesIO(pic))
            a.save("template2pic.png", format="PNG")

            await scoreboard_command.send(MessageSegment.image(pic))
        
            
                
                
    except Exception as e:
        stack_trace = traceback.format_exc()
        error_message = f"处理计分板时出错：\n{stack_trace}"
        await bot.send(event, error_message)
        
        
        

def read_and_parse_scoreboard_file(scoreboard_name="finaltime"):
    """读取并解析计分板文件"""
    # 根据指定的计分板名称生成文件路径
    # file_path = f"/mnt/data/SSoftwareFiles/minecraft/paper1.21.3-parkour/plugins/qwq-spigot-plugin/scoreboard_loggings/{scoreboard_name}/{scoreboard_name}_logging.txt"
    # file_path = f"/mnt/vda1/SSoftwareFiles/minecraft/paper-1.21.3-parkour/paper-1.21.3-parkour/plugins/qwq-spigot-plugin/scoreboard_loggings/{scoreboard_name}/{scoreboard_name}_logging.txt"
    # file_path = f"/mnt/remote_sshfs_233/paper-1.20.4-parkour_scoreboard_loggings/{scoreboard_name}/{scoreboard_name}_logging.txt"
    
    file_path = f"/mnt/vdb1/SSoftwareFiles/minecraft/paper-1.20.4-parkour/paper-1.20.4-parkour/plugins/qwq-spigot-plugin/scoreboard_loggings/{scoreboard_name}/{scoreboard_name}_logging.txt"
    
    # file_path = f"G:/tmp/{scoreboard_name}/{scoreboard_name}_logging.txt"

    scoreboard_entries = []

    uuid_pattern = re.compile(r'^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$', re.IGNORECASE)

    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f:
                parts = line.strip().split(": ")
                if len(parts) == 2:
                    key, value = parts
                    if not uuid_pattern.match(key):  # 排除UUID格式的条目
                        scoreboard_entries.append({"playername": key, "data": int(value)})
    except FileNotFoundError:
        return "FileNotFoundError"  # 如果文件找不到，则返回 None

    return scoreboard_entries

# 封装过滤和排序逻辑的函数
def filter_and_sort_scoreboard(scoreboard_data, is_reversed=False):
    excluded_players = {
        "rank_s", "rank_a", "rank_b", "rank_c", "CONSOLE", "minute", "hour",
        "Hielke", "Hielkez", "DeKracht", 
        "BigSealGuy","Jessuh_","LinerRider","DanielNL","Owlfie_","EELAA","_JoaS","30","314159","_Edgar","_Lory44", "Hexacubed","8","Bullen13","HayCoh","Ozercraftt","2718281","Laxynd","1000","_Dany55","PvPqnda","Shiioya","Lazybrush2","Jast3r",
    }
    filtered_scoreboard_data = [entry for entry in scoreboard_data if entry['playername'] not in excluded_players and entry['data'] != 0]
    sorted_scoreboard_data = sorted(filtered_scoreboard_data, key=lambda x: x['data'], reverse=is_reversed)
    return sorted_scoreboard_data
